#ifndef   _WX_CONFBASE_H_
#define   _WX_CONFBASE_H_

#include "wx/defs.h"
#include "wx/string.h"

class wxArrayString;

// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------

/// shall we be case sensitive in parsing variable names?
#ifndef wxCONFIG_CASE_SENSITIVE
#define  wxCONFIG_CASE_SENSITIVE       0
#endif

/// separates group and entry names (probably shouldn't be changed)
#ifndef wxCONFIG_PATH_SEPARATOR
#define   wxCONFIG_PATH_SEPARATOR     wxT('/')
#endif

/// introduces immutable entries
// (i.e. the ones which can't be changed from the local config file)
#ifndef wxCONFIG_IMMUTABLE_PREFIX
#define   wxCONFIG_IMMUTABLE_PREFIX   wxT('!')
#endif

#include "wx/string.h"

#ifndef   wxUSE_CONFIG_NATIVE
#define wxUSE_CONFIG_NATIVE 1
#endif

enum {
  wxCONFIG_USE_LOCAL_FILE = 1,
  wxCONFIG_USE_GLOBAL_FILE = 2,
  wxCONFIG_USE_RELATIVE_PATH = 4,
  wxCONFIG_USE_NO_ESCAPE_CHARACTERS = 8,
  wxCONFIG_USE_SUBDIR = 16
};

class wxConfigBase {
  public:
    enum EntryType {
      Type_Unknown,
      Type_String,
      Type_Boolean,
      Type_Integer,    // use Read(long *)
      Type_Float       // use Read(double *)
    };
    static wxConfigBase *Set( wxConfigBase *pConfig );
    static wxConfigBase *Get( bool createOnDemand = true ) { if( createOnDemand && ( !ms_pConfig ) ) Create(); return ms_pConfig; }
    static wxConfigBase *Create();
    static void DontCreateOnDemand() { ms_bAutoCreate = false; }
    wxConfigBase( const wxString& appName = wxEmptyString,const wxString& vendorName = wxEmptyString,
                  const wxString& localFilename = wxEmptyString,const wxString& globalFilename = wxEmptyString,
                  long style = 0 );
    virtual ~wxConfigBase();
    virtual void SetPath( const wxString& strPath ) = 0;
    virtual const wxString& GetPath() const = 0;
    virtual bool GetFirstGroup( wxString& str, long& lIndex ) const = 0;
    virtual bool GetNextGroup( wxString& str, long& lIndex ) const = 0;
    virtual bool GetFirstEntry( wxString& str, long& lIndex ) const = 0;
    virtual bool GetNextEntry( wxString& str, long& lIndex ) const = 0;
    virtual size_t GetNumberOfEntries( bool bRecursive = false ) const = 0;
    virtual size_t GetNumberOfGroups( bool bRecursive = false ) const = 0;
    virtual bool HasGroup( const wxString& strName ) const = 0;
    virtual bool HasEntry( const wxString& strName ) const = 0;
    bool Exists( const wxString& strName ) const{
     return HasGroup( strName ) || HasEntry( strName ); }
    virtual EntryType GetEntryType( const wxString& name ) const {
      return HasEntry( name ) ? Type_String : Type_Unknown;
    }
    bool Read( const wxString& key, wxString *pStr ) const;
    bool Read( const wxString& key, wxString *pStr, const wxString& defVal ) const;
    bool Read( const wxString& key, long *pl ) const;
    bool Read( const wxString& key, long *pl, long defVal ) const;
    bool Read( const wxString& key, int *pi ) const;
    bool Read( const wxString& key, int *pi, int defVal ) const;
    bool Read( const wxString& key, double* val ) const;
    bool Read( const wxString& key, double* val, double defVal ) const;
    bool Read( const wxString& key, bool* val ) const;
    bool Read( const wxString& key, bool* val, bool defVal ) const;
    wxString Read( const wxString& key,const wxString& defVal = wxEmptyString ) const{
    wxString s; ( void )Read( key, &s, defVal ); return s; }
    long Read( const wxString& key, long defVal ) const{
     long l; ( void )Read( key, &l, defVal ); return l; }
    bool Write( const wxString& key, const wxString& value ) { return DoWriteString( key, value ); }
    bool Write( const wxString& key, long value ) { return DoWriteLong( key, value ); }
    bool Write( const wxString& key, int value ) { return DoWriteInt( key, value ); }
    bool Write( const wxString& key, double value ) { return DoWriteDouble( key, value ); }
    bool Write( const wxString& key, bool value ) { return DoWriteBool( key, value ); }
    bool Write( const wxString& key, const wxChar *value ) { return Write( key, wxString( value ) ); }
    virtual bool Flush( bool bCurrentOnly = false ) = 0;
    virtual bool RenameEntry( const wxString& oldName,const wxString& newName ) = 0;
    virtual bool RenameGroup( const wxString& oldName,const wxString& newName ) = 0;
    virtual bool DeleteEntry( const wxString& key,bool bDeleteGroupIfEmpty = true ) = 0;
    virtual bool DeleteGroup( const wxString& key ) = 0;
    virtual bool DeleteAll() = 0;
    bool IsExpandingEnvVars() const { return m_bExpandEnvVars; }
    void SetExpandEnvVars( bool bDoIt = true ) { m_bExpandEnvVars = bDoIt; }
    void SetRecordDefaults( bool bDoIt = true ) { m_bRecordDefaults = bDoIt; }
    bool IsRecordingDefaults() const { return m_bRecordDefaults; }
    wxString ExpandEnvVars( const wxString& str ) const;
    wxString GetAppName() const { return m_appName; }
    wxString GetVendorName() const { return m_vendorName; }
    void SetAppName( const wxString& appName ) { m_appName = appName; }
    void SetVendorName( const wxString& vendorName ) { m_vendorName = vendorName; }
    void SetStyle( long style ) { m_style = style; }
    long GetStyle() const { return m_style; }

  protected:
    static bool IsImmutable( const wxString& key ) { return !key.IsEmpty() && key[0] == wxCONFIG_IMMUTABLE_PREFIX; }
    static wxString RemoveTrailingSeparator( const wxString& key );
    virtual bool DoReadString( const wxString& key, wxString *pStr ) const = 0;
    virtual bool DoReadLong( const wxString& key, long *pl ) const = 0;
    virtual bool DoReadInt( const wxString& key, int *pi ) const;
    virtual bool DoReadDouble( const wxString& key, double* val ) const;
    virtual bool DoReadBool( const wxString& key, bool* val ) const;

    virtual bool DoWriteString( const wxString& key, const wxString& value ) = 0;
    virtual bool DoWriteLong( const wxString& key, long value ) = 0;
    virtual bool DoWriteInt( const wxString& key, int value );
    virtual bool DoWriteDouble( const wxString& key, double value );
    virtual bool DoWriteBool( const wxString& key, bool value );

  private:
    // are we doing automatic environment variable expansion?
    bool m_bExpandEnvVars;
    // do we record default values?
    bool m_bRecordDefaults;

    // static variables
    static wxConfigBase *ms_pConfig;
    static bool          ms_bAutoCreate;

    // Application name and organisation name
    wxString          m_appName;
    wxString          m_vendorName;

    // Style flag
    long              m_style;
};

class wxConfigPathChanger {
  public:
    wxConfigPathChanger( const wxConfigBase *pContainer, const wxString& strEntry );
    ~wxConfigPathChanger();
    const wxString& Name() const { return m_strName; }
    void UpdateIfDeleted();
  private:
    wxConfigBase *m_pContainer;   // object we live in
    wxString      m_strName,      // name of entry (i.e. name only)
                  m_strOldPath;   // saved path
    bool          m_bChanged;     // was the path changed?

    DECLARE_NO_COPY_CLASS( wxConfigPathChanger )
};

#define wxConfig  wxFileConfig

wxString wxExpandEnvVars( const wxString &sz );

void wxSplitPath( wxArrayString& aParts, const wxChar *sz );

#endif
